package edu.indiana.cs.b534.torrent.impl;

import edu.indiana.cs.b534.torrent.TorrentException;
import edu.indiana.cs.b534.torrent.message.PeerDictionary;
import edu.indiana.cs.b534.torrent.message.TrackerResponse;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.logging.Logger;

public class TrackerUpdater extends Thread{
	private TorrentManager manager;
	private Map<String, Boolean> deadPeers;
	private static Logger log = Logger.getLogger(TorrentManager.TORRENT_MANAGER_NAME);
	public TrackerUpdater(TorrentManager manager) {
		super();
		this.manager = manager;
		this.setDaemon(true);
		deadPeers = new Hashtable<String, Boolean>();
	}


	@Override
	public void run() {
		while(true){
			try {
				TrackerResponse response = manager.updateFromTracker();
				Vector<PeerDictionary> avalibleNonConnectedPeers = manager.getTorrentContext().getAvalibleNonConnectedPeers();
				for(PeerDictionary peer:response.getPeers()){
					String key = peer.getIP()+peer.getPort();
					if(!deadPeers.containsKey(key)){
						
						if(!avalibleNonConnectedPeers.contains(peer)){
//							System.out.println("Peer "+ peer + "added");
							avalibleNonConnectedPeers.add(peer);
						}
					}
				}
				Thread.sleep(60000);
			} catch (TorrentException e) {
				e.printStackTrace();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	public List<PeerDictionary> findLivePeers(List<PeerDictionary> peers) throws TorrentException {
		
		        List<PeerDictionary> livePeers = new ArrayList<PeerDictionary>();
		
		        for (PeerDictionary peerDictionary : peers) {
		
		            // Create a socket with a timeout
		            try {
		            	if(peerDictionary.getPort() == 0){
		            		continue;
		            	}
		                InetAddress addr = InetAddress.getByName(peerDictionary.getIP());
		                SocketAddress sockaddr = new InetSocketAddress(addr, peerDictionary.getPort());
		
		                // Create an unbound socket
		                Socket sock = new Socket();
		
		                // This method will block no more than timeoutMs.
		                // If the timeout occurs, SocketTimeoutException is thrown.
		                int timeoutMs = 2000;   // 2 seconds
		                //log.info("Connecting to "+ peerDictionary.getIP()+":"+peerDictionary.getPort());
		                sock.connect(sockaddr, timeoutMs);
		                sock.close();
		                livePeers.add(peerDictionary);
		            } catch (Exception e) {
		            	deadPeers.put(peerDictionary.getIP()+peerDictionary.getPort(), true);
		                log.info("Can not connect to the peer in " + peerDictionary.getIP() + ":" + peerDictionary.getPort());
		            }
		        }

		        //livePeers.add(new PeerDictionaryImpl("127.0.0.1", "-ERAN-SRINATH-SEED-1", 6548));
		        return livePeers;
		    }

}
